﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using Dare.Utilities.Data;
using Stone.Components;

namespace Stone.Services.EntityServices
{
    public abstract class EntityServiceTemplate<Entity, EntityKey, EntityDataProvider> : DbServiceBase
        where Entity : EntityBase<Entity, EntityKey>
        where EntityKey : struct
        where EntityDataProvider : Data.DataProviderTemplate<Entity, EntityKey>
    {
        protected EntityDataProvider provider = null;
        public EntityDataProvider DataProvider
        {
            get { return provider; }
        }

        public EntityServiceTemplate(Application app)
            : base(app)
        {
            provider = app.DataProviderManagerFactory.Default.GetDataProvider<EntityDataProvider>();
        }

        public virtual void ProcessBeforeSave(Entity entity) { }
        public virtual void ProcessAfterSaved(Entity entity) { }
        public virtual void ProcessBeforeInsert(Entity entity) { }
        public virtual void ProcessAfterInserted(Entity entity) { }
        public virtual void ProcessBeforeUpdate(Entity entity) { }
        public virtual void ProcessAfterUpdated(Entity entity) { }
        public virtual void ProcessBeforeDelete(EntityKey key) { }
        public virtual void ProcessAfterDeleted(EntityKey key) { }
        public virtual void ProcessAfterRetrieved(IEnumerable<Entity> entities) { }


        /// <summary>
        /// 保存实体
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual bool Save(Entity entity)
        {
            return Execute(delegate(TransactionManager manager)
            {
                if (entity.EntityState == EntityState.New)
                {
                    provider.Insert(manager, entity);
                }
                else if (entity.EntityState == EntityState.Changed)
                {
                    provider.Update(manager, entity);
                }
            }, IsolationLevel.Serializable);
        }

        /// <summary>
        /// 插入实体
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual bool Insert(Entity entity)
        {
            return Execute(delegate(TransactionManager manager)
            {
                ProcessBeforeSave(entity);
                ProcessBeforeInsert(entity);

                provider.Insert(manager, entity);

                ProcessAfterInserted(entity);
                ProcessAfterSaved(entity);

            }, IsolationLevel.Serializable);
        }

        /// <summary>
        /// 更新实体
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual bool Update(Entity entity)
        {
            return Execute(delegate(TransactionManager manager)
            {
                ProcessBeforeSave(entity);
                ProcessBeforeUpdate(entity);

                provider.Update(manager, entity);

                ProcessAfterUpdated(entity);
                ProcessAfterSaved(entity);

            }, IsolationLevel.Serializable);
        }

        /// <summary>
        /// 根据主键删除实体
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public virtual bool Delete(EntityKey key)
        {
            return Execute(delegate(TransactionManager manager)
            {
                ProcessBeforeDelete(key);

                provider.Delete(manager, key);

                ProcessAfterDeleted(key);
            }, IsolationLevel.Serializable);
        }

        /// <summary>
        /// 根据主键获得实体
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public virtual Entity Get(EntityKey key)
        {
            Entity obj = null;

            if (Execute(delegate(TransactionManager manager)
            {
                obj = provider.Get(manager, key);

                ProcessAfterRetrieved(new Entity[] { obj });
            }))
            {
                return obj;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 获得所有实体
        /// </summary>
        /// <returns></returns>
        public virtual List<Entity> GetAll()
        {
            List<Entity> list = null;

            if (Execute(delegate(TransactionManager manager)
            {
                list = provider.GetAll(manager, null, null);

                ProcessAfterRetrieved(list);
            }))
            {
                return list;
            }
            else
            {
                return null;
            }
        }
    }
}
